/* This file is part of FireEscape.
 *
 * FireEscape is the intellectual work of Phillip Cheng & Allen Park.
 * All future releases or modifications of this program must include this
 * attribuation as according to the Creative Commons BY-SA license.
 *
 * FireEscape is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * FireEscape is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FireEscape.  If not, see <http://www.gnu.org/licenses/>.
 *
 * All modifications to this program should include this original statement.
 *
 * If you modify, distribute, or use the program , please contact
 * fireescape@kloudvine.com
 * http://code.google.com/p/fireescape/
 *
 * If you are interested in using FireEscape for your structure, please contact us
 * for support.
 *
 * If you do use FireEscape, please consider donating to the project.
 */
package fireescape;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.SocketHandler;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 * Applet for graphing the data
 * @author chengP
 */
public class GrappherApplet extends Applet {

    private BufferedReader kIn;
    Logger logger = Logger.getLogger("FireEscapeLog");
    ArrayList<String> addresses = new ArrayList<String>();
    private Socket clientSocket;
    private InetSocketAddress server;
    private static final int PORT = 5000;
    public static final int xSize = 900;
    public static final int ySize = 600;

    public GrappherApplet() {
    }

    @Override
    public void init() {

//logging
        DialogApplet g = null;
        //applet dialog pane
        g = new DialogApplet("Connecting to kloudvine.com");
        Component applet = g;
        g.init();

        try {
            // Set System L&F
            UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException ex) {
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        }
        JFrame frame = new JFrame("FireEscape");

        frame.getContentPane().add(applet);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setSize(300, 100);
        frame.setBackground(Color.WHITE);
        double time = System.currentTimeMillis();
        try {

            // get  server address
            URL kloudvine = new URL("http://www.kloudvine.com/loggingServers.txt");
            URLConnection kloudvineConnect = kloudvine.openConnection();
            kIn = new BufferedReader(new InputStreamReader(kloudvineConnect.getInputStream()));
            String inputLine;

            while ((inputLine = kIn.readLine()) != null) {
                addresses.add(inputLine);
            }


            kIn.close();
        } catch (MalformedURLException ex) {
            System.err.println("Server is offline, trying next server");
            System.err.println("Please contact the FireEscape admin.");
            Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
            frame.setVisible(true);
            g.setVisible(true);
        } catch (IOException ex) {
            System.err.println("Server is offline, trying next server");
            System.err.println("Please contact the FireEscape admin.");
            Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
            frame.setVisible(true);
            g.setVisible(true);

        } finally {
        }

        int i = 0;
        Boolean notFound = true;
        while (notFound) {
            try {

                //test log server and get working server
                InetAddress addr = InetAddress.getByName(addresses.get(i));
                int port = 5000;
                SocketAddress server = new InetSocketAddress(addr, port);
                // Create an unbound socket
                Socket clientSocket = new Socket();
                // This method will block no more than timeoutMs.
                // If the timeout occurs, SocketTimeoutException is thrown.
                int timeoutMs = 2000;   // 2 seconds
                clientSocket.connect(server, timeoutMs);
                notFound = false;
                clientSocket.close();

            } catch (SocketTimeoutException ex) {
                i++;
                System.err.println("Server is offline, trying next server");
                System.err.println("Please contact the FireEscape admin.");
                ex.printStackTrace();
                frame.setVisible(true);
                g.setVisible(true);


            } catch (UnknownHostException ex) {
                System.err.println("Kloudvine server offline");
                ex.printStackTrace();
                frame.setVisible(true);
                g.setVisible(true);
            } catch (ConnectException ex) {
                ex.printStackTrace();
                frame.setVisible(true);
                g.setVisible(true);
            } catch (IOException ex) {
                ex.printStackTrace();
                frame.setVisible(true);
                g.setVisible(true);


            } catch (IndexOutOfBoundsException ex) {
                System.err.println("Logging servers offline. Errors not logged.");
                System.err.println("Please contact the FireEscape admin.");
                ex.printStackTrace();

                i = 0;
            }
        }
        try {
            // This block configures the logger with handler and formatter
            SocketHandler sh = new SocketHandler(addresses.get(i), 5000);
            System.out.println(addresses.get(i));
            sh.setFormatter(new SimpleFormatter());
            Logger.getLogger("FireEscapeLog").addHandler(sh);
            Logger.getLogger("FireEscapeLog").setLevel(Level.ALL);
            // the following statement is used to log any messages
            Logger.getLogger("FireEscapeLog").log(Level.INFO, "Client Connected: " + InetAddress.getLocalHost().toString());
        } catch (SecurityException e) {
            e.printStackTrace();
            frame.setVisible(true);
            g.setVisible(true);

        } catch (IOException e) {
            frame.setVisible(true);
            g.setVisible(true);

            e.printStackTrace();
        }
        
        frame.dispose();


        this.setSize(xSize, ySize);


    }

    @Override
    public void paint(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        Image im = createImage(xSize, ySize);
        Grapher grapher = new Grapher();
        grapher.drawScatterGraph(getData(), im);
        g2.drawImage(im, 0, 0, null);
    }

    public ArrayList<Double> getData() {
        int i = 0;
        Boolean notFound = true;
        try {

            // get  server address
            URL kloudvine = new URL("http://www.kloudvine.com/onlineStatus.txt");
            URLConnection kloudvineConnect = kloudvine.openConnection();
            kIn = new BufferedReader(new InputStreamReader(kloudvineConnect.getInputStream()));
            String inputLine = kIn.readLine();
            if (inputLine.equals("offline")) {
                DialogApplet g = new DialogApplet("Thanks for participating! FireEscape Offline.");
                Component applet = g;
                g.init();
                JFrame frame = new JFrame("FireEscape");
                frame.getContentPane().add(applet);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


                frame.pack();
                frame.setSize(300, 100);
                frame.setVisible(true);
                g.setVisible(true);
                Thread.sleep(15000);
                
                System.exit(0);

            }

            kIn.close();
        } catch (MalformedURLException ex) {
            System.err.println("Server is offline, trying next server");
            System.err.println("Please contact the FireEscape admin.");
            Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
            System.exit(-1);

        } catch (IOException ex) {
            System.err.println("Server is offline, trying next server");
            System.err.println("Please contact the FireEscape admin.");
            Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
            System.exit(-1);

        } catch (InterruptedException ex) {
            System.exit(-1);
        }
        //applet dialog pane
        DialogApplet g = new DialogApplet("Connecting to server...");
        Component applet = g;
        g.init();

        try {
            // Set System L&F
            UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException ex) {
        } catch (ClassNotFoundException ex) {
        } catch (InstantiationException ex) {
        } catch (IllegalAccessException ex) {
        }
        JFrame frame = new JFrame("FireEscape");

        frame.getContentPane().add(applet);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setSize(300, 100);
        frame.setBackground(Color.WHITE);
        while (notFound) {
            try {
                Boolean gotData = false;
                clientSocket = new Socket();
                //test log server and get working server
                InetAddress addr = InetAddress.getByName(addresses.get(i));
                server = new InetSocketAddress(addr, PORT);
                // Create an unbound socket
                //System.out.println(addresses.get(i));
                // This method will block no more than timeoutMs.
                // If the timeout occurs, SocketTimeoutException is thrown.
                int timeoutMs = 2000;   // 2 seconds
                clientSocket.connect(server, timeoutMs);
                //System.out.println("Past connect");
                //establish outputs and inputs. Get the initial job
                ObjectOutputStream out = new ObjectOutputStream(clientSocket.getOutputStream());
                //System.out.println("Past get output steram");
                out.writeObject("GetData");
                //System.out.println("Wrote packet");
                ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
                //System.out.println("Past get input stream");
                ArrayList<Double> data = (ArrayList<Double>) in.readObject();
                for (Double d : data) {
                    System.out.println(d);
                }
                //System.out.println("got genome" + genomeID);
                out.flush();
                in.close();
                out.close();
                clientSocket.close();
                frame.dispose();
                
                return data;

            } catch (SocketTimeoutException ex) {
                i++;
                System.err.println("Server is offline, trying next server");
                System.err.println("Please contact the FireEscape admin.");
                Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
                frame.setVisible(true);
                g.setVisible(true);
            } catch (UnknownHostException ex) {
                System.err.println("Server is offline, trying next server");
                System.err.println("Please contact the FireEscape admin.");
                Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
                frame.setVisible(true);
                g.setVisible(true);
            } catch (ConnectException ex) {
                System.err.println("Server is offline, trying next server");
                System.err.println("Please contact the FireEscape admin.");
                Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);
                frame.setVisible(true);
                g.setVisible(true);

            } catch (IOException ex) {
                ex.printStackTrace();
                frame.setVisible(true);
                g.setVisible(true);
            } catch (IndexOutOfBoundsException ex) {
                System.err.println("Fire Escape Servers offline.");
                System.err.println("Please contact the FireEscape admin.");
                Logger.getLogger("FireEscapeLog").log(Level.SEVERE, null, ex);

                i = 0;
            } catch (ClassNotFoundException ex) {
                Logger.getLogger("FireEscapeLog").log(Level.SEVERE, "Server malfunction - server sent a funky class");
                System.exit(-1);
            }
        }
        return null;
    }
}
